home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / futil.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  13KB  |  565 lines

  1. /* Wide AREA INFORMATION SERVER SOFTWARE    
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.  
  4.   
  5.    3/90 Brewster
  6. */
  7.  
  8. /* Change log:
  9.  * $Log:    futil.c,v $
  10.  * Revision 1.21  92/03/24  10:30:41  jonathan
  11.  * Added fix to pathname_directory if no directory part, it puts "./" in the
  12.  * destination.
  13.  * 
  14.  * Revision 1.20  92/02/21  11:05:48  jonathan
  15.  * added RCSIdent
  16.  * 
  17.  * Revision 1.19  92/02/20  14:51:19  jonathan
  18.  * changed include for access() to sys/file.h, since that seems more portable.
  19.  * 
  20.  * Revision 1.18  92/02/18  11:52:43  jonathan
  21.  * conditionalized inclusion of unistd.h for NeXT (use fcntl instead).  This
  22.  * may be a BSD thing.
  23.  * 
  24.  * Revision 1.17  92/02/12  13:19:27  jonathan
  25.  * Added "$Log" so RCS will put the log message in the header
  26.  * 
  27. */
  28.  
  29. #ifndef lint
  30. static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/futil.c,v 1.21 92/03/24 10:30:41 jonathan Exp $";
  31. #endif
  32.  
  33. /* ======================== */
  34. /* ===  File Utilities  === */
  35. /* ======================== */
  36.  
  37. #include <string.h>
  38.  
  39. #ifdef THINK_C
  40.   /* file type info */
  41. #include <pascal.h>        /* for CtoPstr */
  42. #include <FileMgr.h>
  43. #define CREATOR         'WIS1'
  44. #define WAIS_INDEX_FILE_TYPE     'INDX'
  45. #else
  46. #include <sys/types.h> /* for stat and getuid */
  47. #include <sys/stat.h> /* for stat */
  48. #include <sys/param.h> /* for getwd */
  49.  
  50. /* for access() */
  51. #include <sys/file.h>
  52. #endif /* THINK_C */
  53.  
  54. #include "futil.h"
  55. #include "panic.h"
  56.  
  57. /*----------------------------------------------------------------------*/
  58.  
  59. static long numFilesCurrentlyOpen = 0;
  60. static long maxNumFilesOpenAtOneTime = 0;
  61.  
  62. FILE*
  63. fs_fopen(fileName,mode)
  64. char* fileName;
  65. char* mode;
  66. {
  67.   FILE* file = NULL;
  68.   char realMode[100];
  69.   
  70. #ifdef BSD
  71. #define implicitBinary
  72. #endif /* def BSD */
  73. #ifdef ultrix
  74. #define implicitBinary
  75. #endif /* def ultrix */
  76. #ifndef ANSI_LIKE
  77. #define implicitBinary
  78. #endif /* def ANSI_LIKE */
  79.  
  80. #ifdef implicitBinary
  81.    /* these old os's don't handle the binary mode.  Just remove it */
  82.    long i,j;
  83.    for (i = 0L,j = 0; mode[i] != '\0';i++)
  84.     { if (mode[i] != 'b')
  85.     realMode[j++] = mode[i];
  86.     }
  87.    realMode[j] = '\0';
  88.   file = fopen(fileName,realMode);
  89. #else
  90.   file = fopen(fileName,mode);
  91. #endif /* def implicitBinary */
  92.   
  93.   if (file != NULL)
  94.     { numFilesCurrentlyOpen++;
  95.       if (numFilesCurrentlyOpen > maxNumFilesOpenAtOneTime)
  96.     maxNumFilesOpenAtOneTime = numFilesCurrentlyOpen;
  97.     }
  98.   
  99.   return(file);
  100. }
  101.  
  102. /*----------------------------------------------------------------------*/
  103.  
  104. long
  105. fs_fclose(file)
  106. FILE* file;
  107.  
  108. {
  109.   if (file != NULL)
  110.     { numFilesCurrentlyOpen--;
  111.       return(fclose(file));
  112.     }
  113.   else
  114.     return(0L);
  115. }
  116.  
  117. /*----------------------------------------------------------------------*/
  118.  
  119. long fs_fseek(file,offset,wherefrom)
  120. FILE* file;
  121. long offset;
  122. long wherefrom;
  123. {
  124.   long result;
  125.   
  126.   if(NULL == file)
  127.     return -1;
  128.   
  129.   result = fseek(file, offset, wherefrom);
  130.  
  131.   /*
  132.   if(0 != result) 
  133.     panic("A seek failed:  offset %ld, wherefrom %d.\n",offset, wherefrom);
  134.     */
  135.   return result;
  136. }
  137.  
  138. /*----------------------------------------------------------------------*/
  139.  
  140. long fs_ftell(file)
  141. FILE* file;
  142. {
  143.   long result;
  144.   
  145.   if (file == NULL)
  146.     return(0);
  147.     
  148.   result = ftell(file);
  149.   
  150.   if(EOF == result)
  151.     panic("A seek on an index file failed.\n");
  152.  
  153.   return(result);
  154. }
  155.  
  156. /*----------------------------------------------------------------------*/
  157.  
  158. void grow_file(file,length)
  159. FILE* file;
  160. long length;
  161. {
  162.   long current_length;
  163.   s_fseek(file, 0L, SEEK_END);
  164.   current_length = s_ftell(file);
  165.   s_fseek(file, length - current_length, SEEK_END);
  166. }
  167.  
  168. /*----------------------------------------------------------------------*/
  169.  
  170. /* writes the high byte first, this makes reading faster */
  171. long write_bytes(value,size,stream)
  172. long value;
  173. long size;
  174. FILE* stream;
  175. {
  176.   long i;
  177.   long answer;
  178.   if((size < sizeof(long)) && (0 != (value >> (size * 8))))
  179.     panic("In a call to write_bytes, the value %ld can not be represented in %ld bytes", value, size);
  180.   for(i = size - 1; i >= 0; i--){
  181.     answer = putc((value >> (i * 8)) & 0xFF, stream);
  182.   }
  183.   if(ferror(stream) != 0) {
  184.     panic("Write failed");
  185.   }
  186.   return(answer);
  187. }
  188.  
  189. /*----------------------------------------------------------------------*/
  190.  
  191. /* returns EOF if it gets an error */
  192. long read_bytes(n_bytes,stream)
  193. long n_bytes;
  194. FILE *stream;
  195. {
  196.   long answer = 0;
  197.   unsigned long ch;
  198.   long i;
  199.   for(i = 0; i < n_bytes; i++){
  200.     ch = fgetc(stream);
  201.     if(EOF == ch){
  202.       return(EOF);
  203.     }
  204.     answer = (answer << 8) + (unsigned char)ch;
  205.   }
  206.   return(answer);
  207. }
  208.  
  209. /*----------------------------------------------------------------------*/
  210.  
  211. long read_bytes_from_memory(n_bytes,block)
  212. long n_bytes;
  213. unsigned char *block;
  214. {
  215.   long answer = 0;
  216.   unsigned char ch;
  217.   long i;
  218.   for(i = 0; i < n_bytes; i++){
  219.     ch = *(block++);
  220.     answer = (answer << 8) + ch;
  221.   }
  222.   return(answer);
  223. }
  224.  
  225. /*----------------------------------------------------------------------*/
  226.  
  227. time_t file_write_date(filename)
  228. char* filename;
  229. { /* os dependent */
  230. #ifdef THINK_C
  231.     return((time_t)0);  /* not implemented yet */
  232. #else
  233.   struct stat *buf = (struct stat*)s_malloc((size_t)sizeof(struct stat));
  234.   time_t mtime;
  235.  
  236.   if(0 != stat(filename, buf)){
  237.     panic("could not stat %s", filename);
  238.   }
  239.   mtime =  buf->st_mtime;
  240.   s_free(buf);
  241.   return(mtime);
  242. #endif /* THINK_C */
  243. }
  244.  
  245. /*----------------------------------------------------------------------*/
  246.  
  247. long file_length(stream)
  248. FILE* stream;
  249. /* return the length (in bytes) of a stream - leave the current
  250.    position where it was
  251.  */ 
  252. {
  253.   long position = ftell(stream);
  254.   long end = -1;
  255.   s_fseek(stream, 0L, SEEK_END);
  256.   end = ftell(stream);    
  257.   s_fseek(stream,position,SEEK_SET);
  258.   return(end);
  259. }
  260.  
  261. /*----------------------------------------------------------------------*/
  262.  
  263. static char *clean_path _AP((char* filename));
  264.  
  265. static char *clean_path(filename)
  266. char *filename;
  267. /* this takes out the '/../' and the '/./' from the path by modifying 
  268.    the argument and returning it. The pathname passed to it must be a 
  269.    full path. This is not optimized. */
  270. {
  271. #ifndef THINK_C
  272.   char *beginning_ptr = strstr(filename, "/../");
  273.   if(NULL != beginning_ptr){
  274.     /* then we have something to process.
  275.        reverse search for the beginning of the last directory,
  276.        in order to snuff it */
  277.     char *ptr;
  278.     for(ptr = beginning_ptr - 1; ptr >= filename; ptr--){
  279.       if(*ptr == '/'){
  280.     /* then we found the beginning of the path */
  281.     strcpy(ptr, beginning_ptr + strlen("/../") -1);
  282.     clean_path(filename);    /* get the other occurances of /../ */
  283.     break;
  284.       }    
  285.     }
  286.   }
  287.   /* now look for /./ */
  288.   beginning_ptr = strstr(filename, "/./");
  289.   if(NULL != beginning_ptr){
  290.     strcpy(beginning_ptr, beginning_ptr + strlen("/./") -1);
  291.     clean_path(filename);    /* get the other occurances of /./ */
  292.   }
  293. #endif                /* ndef THINK_C */
  294.  
  295.   return(filename);
  296.  
  297. }
  298.  
  299. /*----------------------------------------------------------------------*/
  300.     
  301. char *truename(filename,full_path)
  302. char *filename;
  303. char *full_path;
  304. {
  305.   /* this puts into full_path the full pathname including directory.
  306.    */
  307. #ifdef THINK_C
  308.   strcpy(full_path, filename);
  309.   return(full_path); /* do nothing */
  310. #else
  311.   if('/' == filename[0]){
  312.     /* then it is complete already */
  313.     strcpy(full_path, filename);
  314.     clean_path(full_path);
  315.     return(full_path);
  316.   }
  317.   else{
  318.     getwd(full_path);
  319.     s_strncat(full_path,"/",MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  320.     s_strncat(full_path,filename,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  321.     clean_path(full_path);
  322.     return(full_path);
  323.   }
  324. #endif /* THINK_C */
  325. }
  326.  
  327. /*----------------------------------------------------------------------*/
  328.  
  329. char *pathname_name(pathname)
  330. char *pathname;
  331. /* returns a pointer to the leaf name part of full pathname.
  332.    equivalent to common lisp pathname-name. */
  333. {
  334. #ifdef THINK_C
  335.   char *answer = strrchr(pathname, ':');
  336. #else
  337.   char *answer = strrchr(pathname, '/');
  338. #endif    /* THINK_C */
  339.  
  340.   if(NULL == answer)
  341.     return(pathname);
  342.   return(answer + 1);
  343. }
  344.  
  345. /*----------------------------------------------------------------------*/
  346.  
  347. char *pathname_directory(pathname,destination)
  348. char *pathname;
  349. char *destination;
  350. /* returns a pointer to a string of the directory part of
  351.    the pathname and modifies its destination argument.
  352.    This is the equivalent to the common lisp pathname-directory function. */
  353. {
  354. #ifdef THINK_C
  355.   char *dirptr = strrchr(pathname, ':');
  356. #else
  357.   char *dirptr = strrchr(pathname, '/');
  358. #endif /* THINK_C */
  359.  
  360.   if(NULL == dirptr)
  361. #ifdef THINK_C
  362.     strncpy(destination, pathname, MAX_FILE_NAME_LEN);
  363. #else
  364.     strncpy(destination, "./", MAX_FILENAME_LEN);
  365. #endif /* THINK_C */
  366.   else
  367.     { strncpy(destination, pathname, MAX_FILE_NAME_LEN);
  368.       destination[dirptr - pathname + 1] = '\0';
  369.     }
  370.  
  371.   return(destination);
  372. }
  373.   
  374. /*----------------------------------------------------------------------*/
  375.  
  376. /* Setting the Macintosh File type (requires the MacTraps library) */
  377. /* from Util.c by Harry Morris */
  378.  
  379. #ifdef THINK_C
  380.  
  381. void 
  382. setFileType(fileName,type,creator)
  383. char* fileName;
  384. FType type;
  385. FType creator;
  386.   FInfo info;
  387.   OSErr error;
  388.   
  389.   CtoPstr(fileName);
  390.   error = GetFInfo((StringPtr)fileName,0L,&info);
  391.   if (error != noErr)
  392.     panic("error - Can't get file type of file %s, code %ld\n",
  393.           PtoCstr((char*)fileName),noErr);
  394.   info.fdType = type;
  395.   info.fdCreator = creator;
  396.   error = SetFInfo((StringPtr)fileName,0L,&info);
  397.   if (error != noErr)
  398.     panic("error - Can't change file type of file %s, code %ld\n",
  399.           PtoCstr((char*)fileName),noErr);
  400.   PtoCstr((char*)fileName);
  401. }
  402.  
  403. #endif /* THINK_C */
  404.  
  405. /*----------------------------------------------------------------------*/
  406.  
  407. char *current_user_name()
  408. /* returns the current_user_name as a mail address */
  409. {
  410.   static char answer[200];
  411.   char hostname[120];
  412.   
  413. #ifdef THINK_C
  414.   strcpy(answer,"MAC"); /* could look up the name in the chooser */
  415. #endif /* def THINK_C */
  416.  
  417. #ifdef M_XENIX
  418.   strcpy(answer,"unknown"); /* could look up the name in the chooser */
  419. #endif /* def M_XENIX */
  420.  
  421. #ifndef THINK_C
  422. #ifndef M_XENIX
  423.  
  424. #include <pwd.h>  /* for getpwent */
  425.  
  426.   struct passwd *pwent = getpwuid(getuid());
  427.   strncpy(answer, pwent->pw_name, 200);
  428.   strncat(answer, "@", 200);
  429.   gethostname(hostname, 120);
  430.   strncat(answer, hostname, 200);
  431.  
  432. #endif /* ndef M_XENIX */
  433. #endif /* ndef THINK_C */
  434.  
  435.   return(answer);
  436. }
  437.  
  438. /*----------------------------------------------------------------------*/
  439.  
  440. boolean probe_file(filename)
  441. char *filename;
  442. /* return true if it is there, false otherwise.
  443.    Can this be done faster? */
  444. {
  445.   if (filename == NULL)
  446.     return(false);
  447.   else if (access(filename,R_OK) == 0)
  448.     return(true);
  449.   else
  450.     return(false);
  451. }
  452.  
  453. /*----------------------------------------------------------------------*/
  454.  
  455. boolean probe_file_possibly_compressed(filename)
  456. char *filename;
  457. /* return true if it is there, false otherwise.
  458.    Can this be done faster? */
  459. {
  460.   if (filename == NULL)
  461.     return(false);
  462.   else if (!probe_file(filename))
  463.     { /* try the compression */
  464.       char buffer[ MAX_FILENAME_LEN * 2 ];
  465.       strcpy(buffer, filename);
  466.       strcat(buffer, ".Z");
  467.       return(probe_file(buffer));
  468.     }
  469.   else
  470.     return(true);
  471. }
  472.  
  473. /*----------------------------------------------------------------------*/
  474.  
  475. /* this opens the file for writing (append)p and then closes it again */
  476. boolean touch_file(filename)
  477. char *filename;
  478. /* return false if error, true otherwise. */
  479. {
  480.   FILE *stream = NULL;
  481.   if (filename == NULL)
  482.     return(false);
  483.   stream = s_fopen(filename, "a");
  484.   if (NULL == stream)
  485.     return(false);
  486.   else
  487.     { s_fclose(stream);
  488.       return(true);
  489.     }
  490. }
  491.  
  492. /*----------------------------------------------------------------------*/
  493.  
  494. char *merge_pathnames(pathname, directory)
  495. char *pathname;
  496. char *directory;
  497. {
  498.   /* if the pathname is not complete, then it puts on the directory
  499.      component and returns it in a static variable.  This is Unix specific */
  500.   static char answer[MAX_FILENAME_LEN + 1];
  501.   if((pathname[0] == '/') || (NULL == directory) || directory[0] == '\0')
  502.     return(pathname);
  503.   else{
  504.     answer[0] = '\0';
  505.     strncat(answer, directory, MAX_FILENAME_LEN);
  506. #ifdef THINK_C
  507.     if(directory[strlen(directory) - 1] != ':')
  508.       strncat(answer, ":", MAX_FILENAME_LEN);
  509. #else
  510.     if(directory[strlen(directory) - 1] != '/')
  511.       strncat(answer, "/", MAX_FILENAME_LEN);
  512. #endif
  513.     strncat(answer, pathname, MAX_FILENAME_LEN);
  514.   }
  515.   /* should this call truename? */
  516.   return(answer);
  517. }
  518.  
  519. /*----------------------------------------------------------------------*/
  520.  
  521.  
  522. boolean 
  523. read_string_from_file(stream,array,array_length)
  524. FILE *stream;
  525. char *array;
  526. long array_length;
  527. /* returns true if it wins. */
  528. {
  529.   long ch;
  530.   long char_count = 0;
  531.  
  532.   array[0] = '\0';
  533.   while(true){
  534.     ch = fgetc(stream);
  535.     if(EOF == ch){
  536.       array[char_count] = '\0';
  537.       return(false);
  538.     }
  539.     else if(char_count == array_length){        
  540.       array[char_count] = '\0';
  541.       return(false);
  542.     }
  543.     else if('\0' == ch){
  544.       array[char_count] = '\0';
  545.       return(true);
  546.     }
  547.     else
  548.       array[char_count++] = ch;
  549.   }
  550. }
  551.  
  552.  
  553. /* counts the lines in a file */
  554. long count_lines(stream)
  555. FILE *stream;
  556. {
  557.   long answer = 1;
  558.   char line[100];
  559.   fseek(stream, 0L, SEEK_SET);    
  560.   while(NULL != fgets(line,100L,stream))
  561.     answer++;
  562.   return(answer);
  563. }
  564.